package com.atguigu.tingshu.album.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.vo.album.TrackInfoVo;
import com.atguigu.tingshu.vo.album.TrackListVo;
import com.atguigu.tingshu.vo.album.TrackMediaInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private VodService vodService;

    @Autowired
    private TrackStatMapper trackStatMapper;

    /**
     * 保存声音，发起内容审核任务
     *
     * @param trackInfoVo
     * @param userId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
        //1.根据专辑ID查询专辑信息 得到现有声音数量
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
        Integer includeTrackCount = albumInfo.getIncludeTrackCount();

        //2.保存声音记录
        TrackInfo trackInfo = BeanUtil.copyProperties(trackInfoVo, TrackInfo.class);
        //2.1 封装普通属性
        trackInfo.setUserId(userId);
        trackInfo.setSource(SystemConstant.TRACK_SOURCE_USER);
        trackInfo.setStatus(SystemConstant.TRACK_STATUS_REVIEWING); //审核中
        if (StringUtils.isBlank(trackInfo.getCoverUrl())) {
            //如果前端未提交封面，使用专辑封面
            trackInfo.setCoverUrl(albumInfo.getCoverUrl());
        }
        //2.2 计算声音排序值
        trackInfo.setOrderNum(includeTrackCount + 1);
        //2.3 调用点播平台获取音频文件详情得到：时长、大小、类型
        TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
        if (trackMediaInfoVo != null) {
            trackInfo.setMediaDuration(BigDecimal.valueOf(trackMediaInfoVo.getDuration()));
            trackInfo.setMediaSize(trackMediaInfoVo.getSize());
            trackInfo.setMediaType(trackMediaInfoVo.getType());
        }
        //2.4 保存声音
        baseMapper.insert(trackInfo);
        Long trackId = trackInfo.getId();

        //3.保存声音统计
        this.saveTrackStat(trackId, SystemConstant.TRACK_STAT_PLAY, 0);
        this.saveTrackStat(trackId, SystemConstant.TRACK_STAT_COLLECT, 0);
        this.saveTrackStat(trackId, SystemConstant.TRACK_STAT_PRAISE, 0);
        this.saveTrackStat(trackId, SystemConstant.TRACK_STAT_COMMENT, 0);

        //4.更新专辑包含声音数量
        albumInfo.setIncludeTrackCount(includeTrackCount + 1);
        albumInfoMapper.updateById(albumInfo);

        //5.TODO 发起异步音视频审核任务 更新声音表 审核任务ID
        //5.1 方式一：如果是异步开启线程发起审核任务，将更新声音表逻辑放在审核方法里。不需要返回结果
        //5.2 方式二：如果是同步程发起审核任务，得到审核任务ID，同步更新声音表
        String reviewTaskId = vodService.startReviewTask(trackInfo.getMediaFileId());
        trackInfo.setReviewTaskId(reviewTaskId);
        trackInfoMapper.updateById(trackInfo);
    }

    @Override
    public void saveTrackStat(Long trackId, String statType, int statNum) {
        TrackStat trackStat = new TrackStat();
        trackStat.setTrackId(trackId);
        trackStat.setStatType(statType);
        trackStat.setStatNum(statNum);
        trackStatMapper.insert(trackStat);
    }

    /**
     * 获取当前用户声音分页列表
     *
     * @param pageInfo
     * @param trackInfoQuery
     * @return
     */
    @Override
    public Page<TrackListVo> findUserTrackPage(Page<TrackListVo> pageInfo, TrackInfoQuery trackInfoQuery) {
        return trackInfoMapper.findUserTrackPage(pageInfo, trackInfoQuery);
    }

    /**
     * 修改声音
     *
     * @param id
     * @param trackInfoVo
     */
    @Override
    public void updateTrackInfo(Long id, TrackInfoVo trackInfoVo) {
        //1.根据声音ID查询声音记录 获取原来音频ID
        TrackInfo trackInfo = baseMapper.selectById(id);
        String oldMediaFileId = trackInfo.getMediaFileId();
        if (!oldMediaFileId.equals(trackInfoVo.getMediaFileId())) {
            //2.有变更 再次获取最新文件音频信息 更新：时长、大小、类型
            TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
            if (trackMediaInfoVo != null) {
                trackInfo.setMediaFileId(trackInfoVo.getMediaFileId());
                trackInfo.setMediaUrl(trackInfoVo.getMediaUrl());
                trackInfo.setMediaDuration(BigDecimal.valueOf(trackMediaInfoVo.getDuration()));
                trackInfo.setMediaSize(trackMediaInfoVo.getSize());
                trackInfo.setMediaType(trackMediaInfoVo.getType());
            }
            //3.从点播平台删除旧的音频
            log.info("更新专辑线程：{}", Thread.currentThread().getName());
            vodService.deleteMedia(oldMediaFileId);
            //TODO 变更后音频文件发起审核任务，重新关联审核任务ID
            //5.TODO 发起异步音视频审核任务 更新声音表 审核任务ID
            //5.1 方式一：如果是异步开启线程发起审核任务，将更新声音表逻辑放在审核方法里。不需要返回结果
            //5.2 方式二：如果是同步程发起审核任务，得到审核任务ID，同步更新声音表
            String reviewTaskId = vodService.startReviewTask(trackInfo.getMediaFileId());
            trackInfo.setStatus(SystemConstant.TRACK_STATUS_REVIEWING);
            trackInfo.setReviewTaskId(reviewTaskId);
            trackInfoMapper.updateById(trackInfo);
        }
        //其他属性更新
        trackInfo.setTrackTitle(trackInfoVo.getTrackTitle());
        trackInfo.setCoverUrl(trackInfoVo.getCoverUrl());
        trackInfo.setTrackIntro(trackInfoVo.getTrackIntro());
        trackInfo.setIsOpen(trackInfoVo.getIsOpen());
        baseMapper.updateById(trackInfo);
    }

    /**
     * 删除声音
     *
     * @param id 声音ID
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeTrackInfo(Long id) {
        //1.根据声音ID查询被删除声音记录 得到专辑ID及声音序号
        TrackInfo trackInfo = baseMapper.selectById(id);
        Long albumId = trackInfo.getAlbumId();
        Integer orderNum = trackInfo.getOrderNum();
        //2.更新该下专辑下声音序号确保连续
        LambdaUpdateWrapper<TrackInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(TrackInfo::getAlbumId, albumId);
        updateWrapper.gt(TrackInfo::getOrderNum, orderNum);
        updateWrapper.setSql("order_num = order_num - 1");
        baseMapper.update(null, updateWrapper);

        //3.删除声音记录
        baseMapper.deleteById(id);

        //4.删除声音统计
        trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, id));

        //5.更新专辑包含声音数量-1
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
        albumInfoMapper.updateById(albumInfo);

        //6.删除点播平台音频文件
        vodService.deleteMedia(trackInfo.getMediaFileId());
    }
}
